#include <iostream>
using std::cout;
using std::endl;
class Data{
public:
    int getData(){
        return _data;
    }

private:
    int _data = 10;
};
class MiddleLayer{
public:
    MiddleLayer(Data * p)
    :_pdata(p)
    {
        //这里面的指针数据成员使用的是浅拷贝操作
    }

    ~MiddleLayer(){
        if(_pdata){
            delete _pdata;
            _pdata = nullptr;
        }
    }

    //方案一：提供一个get，将指针暴露出来
    Data * get(){
        return _pdata;
    }

    //方案二：重载成员访问运算符(箭头访问运算符、解引用运算符)
    //这两个运算符的特征是默认仅可以在指针中使用，不可以在对象中使用
    //进行了重载之后，可以在对象中使用该运算符 iterator
    Data * operator->(){
        return _pdata;
    }

    //重载解引用运算符
    //让对象的行为和原生裸指针的使用形式完全一致
    Data & operator*(){
        return *_pdata;
    }

private:
    Data * _pdata;
};


void test(){
    //此时只需要new，不需要调用delete
    //依然不会有任何的内存泄漏问题
    //主要的原因在于使用一个栈对象的生命周期来管理堆资源
    //栈对象被销毁时，会调用析构函数，析构函数执行会
    //触发delete操作
    MiddleLayer ml(new Data());
    //此时还会有新的问题，那么就是如何访问data对象里面的成员函数呢？
    //参考xmind里面的两种方案
    cout << ml.get()->getData() << endl;
    //实现了箭头访问运算符的重载，有什么好处呢？？？
    //好处是指针放置在一个栈对象中，使用的形式不变
    //之前如何使用，现在依然如何去使用
    cout << ml->getData() << endl;
    //等价于
    cout << ml.operator->()->getData() << endl;
}

void test2(){
    MiddleLayer ml(new Data());
    cout << (*ml).getData() << endl;
    //等价于
    cout << ml.operator*().getData() << endl;
    //如果使用裸指针如何操作呢？
    cout << (*(ml.get())).getData() << endl;
}


//箭头和解引用必须是成员函数形式的重载，不可以是普通函数之友元




int main()
{
    test2();
    return 0;
}

